#ifndef _THREADPOOL_HPP
#define _THREADPOOL_HPP

#include <iostream>
#include <queue>
#include <cstdlib>
#include <pthread.h>
#include "Log.hpp"

#define THREAD_NUM 5

// 设计成单例模式
template<class Task>
class ThreadPool
{
  private:
      int thread_num;               // 线程池线程数量
      pthread_mutex_t mtx;          // 互斥锁
      pthread_cond_t empty;          // 条件变量
      static ThreadPool* inst;      // 静态指针
      std::queue<Task> task_queue;  // 任务队列
      bool stop;

      ThreadPool(int _thread_num = THREAD_NUM)
        :thread_num(_thread_num), stop(false)
      {
          // 初始化
          pthread_mutex_init(&mtx, nullptr);
          pthread_cond_init(&empty, nullptr);
      }

      ThreadPool(const ThreadPool&) = delete;
      ThreadPool& operator=(const ThreadPool&) = delete;
  public:
      static ThreadPool* Getinstance(int num = THREAD_NUM)
      {
          // 单例模式加锁
          static  pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
          // 双检锁提高效率
          if(inst == nullptr)
          {
              pthread_mutex_lock(&lock);
              if(nullptr == inst)
              {
                  inst = new ThreadPool(num);
                  // 同时初始化
                  inst->InitThreadPool();
              }
          }

          return inst;
      }

      void Lock()
      {
          pthread_mutex_lock(&mtx);
      }

      void Unlock()
      {
          pthread_mutex_unlock(&mtx);
      }

      bool TaskQueueEmpty()
      {
          return task_queue.size() ? false : true;
      }
      
      void Wait()
      {
          pthread_cond_wait(&empty, &mtx);
      }

      void WakeUp()
      {
          // 避免惊群现象，只唤醒单个线程
          pthread_cond_signal(&empty);
      }

      static void* ThreadRoutine(void* args)
      {
          ThreadPool* tp = (ThreadPool*)(args);
          while(true)
          {
              tp->Lock();
              // 获得任务
              Task t;
              // 使用while可以防止被伪唤醒
              while(tp->TaskQueueEmpty())
              {
                  tp->Wait();
              }

              tp->PopTask(t);
              tp->Unlock();
              // 处理任务
              t.ProcessOn();
              LOG(INFO, "Handler Task Success!");  
          }
      }

      void PopTask(Task& t)
      {
          t = task_queue.front();
          task_queue.pop();
          LOG(INFO, "Pop Task Success!");
      }

      void PushTask(Task t)
      {
          // Push需要进行加锁
          Lock();
          task_queue.push(t);
          Unlock();
          // 插入任务后，唤醒线程
          WakeUp();
          LOG(INFO, "Push Task Success!");
      }

      void InitThreadPool()
      {
          
          for(int i = 0; i < thread_num; ++i)
          {
              pthread_t tid;
              if(pthread_create(&tid, nullptr, ThreadRoutine, this) != 0)
              {
                  // 创建失败
                  LOG(FATAL, "Thread Create Error!");
                  exit(1);
              }
          }

          // 创建成功
          LOG(INFO, "Thread Create Success!");
      }

      ~ThreadPool()
      {
          pthread_mutex_destroy(&mtx);
          pthread_cond_destroy(&empty);
      }
};

// 初始化静态指针
template<class Task>
ThreadPool<Task>* ThreadPool<Task>::inst = nullptr;

#endif
